package com.superview.action;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.InterceptorRef;
import org.apache.struts2.convention.annotation.InterceptorRefs;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.ParentPackage;

import steed.action.BaseAction;
import steed.hibernatemaster.domain.BaseDatabaseDomain;
import steed.util.base.BaseUtil;
@Namespace("/download")
@ParentPackage(value = "steed")
@InterceptorRefs({ @InterceptorRef(value = "mydefault") })
public class DownloadAction extends BaseAction<BaseDatabaseDomain>{
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;
	
//	private static String fileUri = "C:/develop/git/virtualhuman/chaowei-speech-txt-align/corpus/chaowei.wav";
	private static String fileUri = "chaowei-speech-txt-align/corpus/chaowei.wav";
	/**
	 * 文件下载
	 * 
	 * @param filename 要下载的文件名称
	 * @throws IOException
	 */
	@Action("downloadFile")
	public String downloadFile() {
		String path = getRequest().getContextPath();
//		String filename = "FCHENLI01.wav";
		String filename = fileUri;
		BaseUtil.out(path +filename);
		File downloadFile = new File(path + filename);
		downloadFileRanges(downloadFile);
		//fileDownload(downloadFile);
		return null;
	}
//	@Action("downloadFile")
//	public void downloadFile() throws IOException {
//		HttpServletRequest request = getRequest();
//        HttpServletResponse response = getResponse();
//
//		String path = request.getContextPath();
//		BaseUtil.out(path + "FCHENLI01.wav");
//		File file = new File(path + "FCHENLI01.wav");
//        response.setContentLength((int) file.length());
//        response.setCharacterEncoding("utf-8");
//        response.setContentType("application/octet-stream");
//        response.setHeader("Content-Disposition", "attachment;filename='back_to_the_sea-wallpaper-2880x1800.jpg'");
//
//        byte[] buffer = new byte[400];
//        int len = 0;
//
//        InputStream is = new FileInputStream(file);
//        OutputStream os = response.getOutputStream();
//
//        while((len = is.read(buffer)) != -1) {
//            os.write(buffer, 0, len);
//        }
//
//        os.close();
//        is.close();
//	}
	/**
	 * * 文件下载(支持断点续传) * @param file * @return
	 */
	private void downloadFileRanges(File file) {
		if (!file.exists()) {
			// 文件不存在
			return;
		} else {
			FileInputStream fis = null;
			OutputStream outPut = null;
			try {
				fis = new FileInputStream(file);
				getResponse().setHeader("Accept-Ranges", "bytes");
				// 下载开始字节
				long downBegin = 0;
				// 文件大小
				long fileSize = 0;
				fileSize = file.length();
				// 如果是第一次下,还没有断点续传,状态是默认的 200,无需显式设置
				// 客户端请求的下载的文件块的开始字节
				if (getRequest().getHeader("Range") != null) {
					// 如果是下载文件的范围而不是全部,向客户端声明支持并开始文件块下载
					getResponse().setStatus(javax.servlet.http.HttpServletResponse.SC_PARTIAL_CONTENT);
					// 从请求中得到开始的字节
					downBegin = Long.parseLong(getRequest().getHeader("Range").replaceAll("bytes=", "").replaceAll("-", ""));
				}
				// 下载的文件(或块)长度
				getResponse().setHeader("Content-Length", new Long(fileSize - downBegin).toString());
				if (downBegin != 0) {
					// 不是从最开始下载,
					getResponse().setHeader("Content-Range", "bytes " + new Long(downBegin).toString() + "-"
							+ new Long(fileSize - 1).toString() + "/" + new Long(fileSize).toString());
				}
				// 响应的格式是:
				getResponse().setContentType("application/octet-stream");
				// 为客户端下载指定默认的下载文件名称
				String fileName = getDownloadChineseFileName("diaoni ");
				//response.setHeader("Content-Disposition",
				//"attachment;filename=" + fileName + "");

				getResponse().reset();
				getResponse().addHeader("Content-Disposition",
						"attachment;filename=" + java.net.URLEncoder.encode(fileName, "utf-8"));
				getResponse().addHeader("Content-Length", "" + file.length());

				fis.skip(downBegin);
				byte[] b = new byte[1024];
				int len;
				outPut = getResponse().getOutputStream();
				while ((len = fis.read(b)) != -1) {
					outPut.write(b, 0, len);
					//response.flushBuffer();
				}
				outPut.flush();
				fis.close();
			} catch (FileNotFoundException e) {
				System.out.println("error");
			} catch (IOException e) {
				/**
				 * 在写数据的时候 对于 ClientAbortException 之类的异常 是因为客户端取消了下载，而服务器端继续向浏览器写入数据时，
				 * 抛出这个异常，这个是正常的。 尤其是对于迅雷这种吸血的客户端软件。 明明已经有一个线程在读取 bytes=1275856879-1275877358，
				 * 如果短时间内没有读取完毕，迅雷会再启第二个、第三个。。。线程来读取相同的字节段， 直到有一个线程读取完毕，迅雷会 KILL
				 * 掉其他正在下载同一字节段的线程， 强行中止字节读出，造成服务器抛 ClientAbortException。 所以，我们忽略这种异常
				 */
			} finally {
				if (fis != null) {
					try {
						fis.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
				if (outPut != null) {
					try {
						outPut.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}

			}
		}
	}

	/**
	 * * 如果下载文件名为中文，进行字符编码转换 * @param paramName * @return downloadChineseFileName
	 */
	private String getDownloadChineseFileName(String paramName) {
		String downloadChineseFileName = "";
		try {
			downloadChineseFileName = new String(paramName.getBytes("GBK"), "ISO8859-1");
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		}
		return downloadChineseFileName;
	}

	/**
	 * 文件下载(不支持断点续传)
	 * 
	 * @param file
	 * @throws IOException
	 */

	private void fileDownload(File file) throws IOException {
		// 以流的形式下载文件。
		InputStream fis = new BufferedInputStream(new FileInputStream(file));
		byte[] buffer = new byte[fis.available()];
		fis.read(buffer);
		fis.close();

		// 清空response
		getResponse().reset();
		getResponse().addHeader("Content-Disposition",
				"attachment;filename=" + java.net.URLEncoder.encode("", "utf-8"));
		getResponse().addHeader("Content-Length", "" + file.length());
		OutputStream os = new BufferedOutputStream(getResponse().getOutputStream());
		getResponse().setContentType("application/octet-stream");
		os.write(buffer);
		os.flush();
		os.close();
	}
	public static void setFileUri(String fileUri) {
		DownloadAction.fileUri = fileUri;
	}
}
